package Root;

import java.awt.AWTException;
import java.awt.GraphicsDevice;
import java.awt.GraphicsEnvironment;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.TreeMap;

import javax.swing.JOptionPane;

import A002_Obrazek._A_OBRAZEK;
import A003_NagrajObraz.test;

public class _B_SZUKAJ_BUFF_A_OBRAZEK {
	
	private Robot rob;

	private TreeMap<Integer,_punktData> integery; // zapiz znalezionych punktow
	private TreeMap<String, _punktData> stringi;
	private int _IZPix; //Ilosc znalezionych pixeli
	
	boolean diag = false;

	private Rectangle _AktywnyObszarMonitora; // do obliczenia poprawnego obliczenia odcinak w razie wielu monitorow
	private Rectangle _recObrazka;
	
	public _B_SZUKAJ_BUFF_A_OBRAZEK(Rectangle _AktywnyObszarMonitora) {
		this._AktywnyObszarMonitora = _AktywnyObszarMonitora;
		try {
			rob = new Robot();
		} catch (AWTException e) {
			e.printStackTrace();
		}
	}
	
	//Szukanie obrazka STRINGI
	public TreeMap<String, _punktData> _FF_String_1obraz (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <String, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			_A_OBRAZEK... iobrazki){
			
			this.integery = null;
			
			if (dane == null){
				this.stringi = new TreeMap<String, _punktData>();
			} else {
				dane.clear();
				this.stringi = dane;
			}	
			
				for ( _A_OBRAZEK a: iobrazki){
					if (a!=null)
					_A_Find(_ZrzutZewnetrzny, Xodniesienia, Yodniesienia, a);
				}
				
				if (diag){
					for(String ab : stringi.keySet()){
						System.out.println(stringi.get(ab).toString());
					};
					}

				return stringi;
			}
	
	//Szukanie obrazka INTEGER
		public TreeMap<Integer, _punktData> _FF_Integer_1obraz (
				BufferedImage _ZrzutZewnetrzny,
				TreeMap <Integer, _punktData> dane,
				int Xodniesienia, 
				int Yodniesienia, 
				_A_OBRAZEK... iobrazki){
				
				this.stringi = null;
				
				if (dane == null){
					this.integery = new TreeMap<Integer, _punktData>();
				} else {
					dane.clear();
					this.integery = dane;
				}	
				
					for ( _A_OBRAZEK a: iobrazki){
						if (a!=null)
						_A_Find(_ZrzutZewnetrzny, Xodniesienia, Yodniesienia, a);
					}
					
					if (diag){
						for(Integer ab : integery.keySet()){
							System.out.println(integery.get(ab).toString());
						};
						}

					return integery;
				}
	
	public TreeMap<Integer, _punktData> _FF_Integer (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <Integer, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			_A_OBRAZEK... iobrazki){
			
			this.integery = null;
			
			if (dane == null){
				this.integery = new TreeMap<Integer, _punktData>();
			} else {
				dane.clear();
				this.integery = dane;
			}	
			
				for ( _A_OBRAZEK a: iobrazki){
					if (a!=null)
					_A_Find(_ZrzutZewnetrzny, Xodniesienia, Yodniesienia, a);
				}
				
				if (diag){
					for(String ab : stringi.keySet()){
						System.out.println(stringi.get(ab).toString());
					};
					}

				return integery;
			}
	
	public TreeMap<String, _punktData> _FF_String (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <String, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			Hashtable<String, _A_OBRAZEK>... ArryList_obrazkow)
			{
				LinkedList<_A_OBRAZEK> LikedListObrazki = new LinkedList<>();
				for (Hashtable<String, _A_OBRAZEK> a: ArryList_obrazkow){
					for (String ob : a.keySet()){
						LikedListObrazki.add(a.get(ob));
					}
				}

				return _FF_String(_ZrzutZewnetrzny, dane, Xodniesienia, Yodniesienia, LikedListObrazki);
			}
	
	public TreeMap<String, _punktData> _FF_String (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <String, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			ArrayList<_A_OBRAZEK> ArryList_obrazkow)
			{
				LinkedList<_A_OBRAZEK> LikedListObrazki = new LinkedList<>();
				for (_A_OBRAZEK a: ArryList_obrazkow){
					LikedListObrazki.add(a);
				}

				return _FF_String(_ZrzutZewnetrzny, dane, Xodniesienia, Yodniesienia, LikedListObrazki);
			}
			
	
	/**
	 * @param _ZrzutZewnetrzny
	 * @param dane
	 * @param Xodniesienia
	 * @param Yodniesienia
	 * @param tolerKoloru
	 * @param tolerProc
	 * @param kolorFix
	 * @param linkedListobrazkow
	 * @return
	 */
	public TreeMap<String, _punktData> _FF_String (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <String, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			LinkedList<_A_OBRAZEK> linkedListobrazkow)
			{
		if (linkedListobrazkow == null | linkedListobrazkow.size() == 0) return null;
		
		this.integery = null;
		
		if (dane == null){
			this.stringi = new TreeMap<String, _punktData>();
		} else {
			dane.clear();
			this.stringi = dane;
		}	
						
		for (_A_OBRAZEK el : linkedListobrazkow){
			
			_A_Find(_ZrzutZewnetrzny, Xodniesienia, Yodniesienia, el);
		}
		
		if (diag){
			for(String ab : stringi.keySet()){
				System.out.println(stringi.get(ab).toString());
			};
			}
		
		return stringi;
		
			}
	
	
	/**
	 * @param _ZrzutZewnetrzny
	 * @param dane
	 * @param Xodniesienia
	 * @param Yodniesienia
	 * @param tolerKoloru
	 * @param tolerProc
	 * @param kolorFix
	 * @param linkedListobrazkow
	 * @return
	 */
	public TreeMap<Integer, _punktData> _FF_Integer (
			BufferedImage _ZrzutZewnetrzny,
			TreeMap <Integer, _punktData> dane,
			int Xodniesienia, 
			int Yodniesienia, 
			LinkedList<_A_OBRAZEK> linkedListobrazkow)
			{
		
		if (linkedListobrazkow == null | linkedListobrazkow.size() == 0) return null;
		
		this.stringi = null;
		
		if (dane == null){
			this.integery = new TreeMap<Integer,_punktData>();
		} else {
			dane.clear();
			this.integery = dane;
		}
		
		for (_A_OBRAZEK el : linkedListobrazkow){
			
			_A_Find(_ZrzutZewnetrzny, Xodniesienia, Yodniesienia, el);
		}
		
		if (diag){
			for(Integer ab : integery.keySet()){
				System.out.println(integery.get(ab).toString());
			};
			}
		
		return integery;
	}
	
	
	private  void _A_Find( BufferedImage _zrzut, int Xodniesienia, int Yodniesienia, _A_OBRAZEK el){
		if (_zrzut!=null) _recObrazka = new Rectangle(_zrzut.getWidth(), _zrzut.getHeight());
		else {
			System.err.print("Szukacz - Brak zrzutu ");
			return;
		}
		
		long CzasIn = System.currentTimeMillis();
		long CzasInStatystyka = System.currentTimeMillis();
		
		if (diag) System.out.print("Szukam elementu nazwa " + el._NazwaObrazu + " ");
		
		for (int yz = 0; yz < _zrzut.getHeight(); yz++){
			for (int xz = 0; xz < _zrzut.getWidth(); xz++){
				
							
				if ((xz - el._startX1) + el._startX2 < _zrzut.getWidth() && yz + el._startY2 < _zrzut.getHeight()){
					
					/*if (DO_Start_AObrazek._window.frame.isVisible()){
						System.out.println("_obrazek " + el._NazwaObrazu);
						System.out.println("_zrzut x/y/w/h  " + _zrzut.getMinX() + " / " + _zrzut.getMinY() + " / "+ _zrzut.getWidth() + " / "+ _zrzut.getHeight() + " / ");	
						System.out.println("xz / yz " + xz + " / " + yz);
						System.out.println("el._startX1 " + el._startX1 + " el._startX2 " + el._startX2);
						System.out.println("(xz - el._startX1) + el._startX2 < _zrzut.getWidth() " + ((xz - el._startX1) + el._startX2 < _zrzut.getWidth()) );
						System.out.println("yz + el._startY2 < _zrzut.getHeight() " + (yz + el._startY2 < _zrzut.getHeight()) );
						System.out.println("");
						}*/
					
					// wejscie do przesukiwania ->START
					if ((PW (_zrzut.getRGB(xz, yz), el._Pierwszypixel, el.tolerancja) 
							&& PW (_zrzut.getRGB((xz - el._startX1) + el._startX2, yz + el._startY2), el._Ostatnipixel, el.tolerancja)) | el.kolorFixUzyj){
												
						//boolean test = szansa (_zrzut, xz - el._startX1, yz, el);
						
						if (szansa (_zrzut, xz - el._startX1, yz, el)) {
							//rob.mouseMove(xz, yz);
							//if (diag)System.out.print ("Znalazlem" + "\n");
							
							int xnewOb = _recObrazka.x+xz - el._startX1 + _AktywnyObszarMonitora.x;
							int ynewOb = _recObrazka.y + yz + _AktywnyObszarMonitora.y;
							int odc = odcinek (_recObrazka.x + Xodniesienia, _recObrazka.y + Yodniesienia, xnewOb, ynewOb);
							if (integery != null ){
								integery.put(odc, new _punktData(odc, xnewOb, ynewOb, el._NazwaObrazu, el, System.currentTimeMillis() - CzasInStatystyka, this._IZPix));
							} else if (stringi != null){
								stringi.put(el._NazwaObrazu, new _punktData(odc, xnewOb, ynewOb, el._NazwaObrazu, el, System.currentTimeMillis() - CzasInStatystyka, this._IZPix));

							}
						} 
						
						
					}
				
				}
				
			}
		}
		
		//if (diag)System.out.println ("Czas szukania " + (System.currentTimeMillis()-CzasIn));	
		return;
	}
	
	
	
	private boolean szansa (BufferedImage _zrzut, int xz, int yz, _A_OBRAZEK el){
		_IZPix = 0;
				
		for (int yo = 0; yo < el._filtrCrop.getHeight(); yo++){
			for (int xo = 0; xo < el._filtrCrop.getWidth(); xo++){
				
				int xtmpz = xz + xo;
				int ytmpz = yz + yo;

				
				if (xtmpz < _zrzut.getWidth() & ytmpz < _zrzut.getHeight() & xtmpz >= 0 & ytmpz >= 0 ){
						
					if ( el._filtrCrop.getRGB(xo, yo) != -1 ){
						//szegolowe
						if (!el.kolorFixUzyj && PW (_zrzut.getRGB (xtmpz, ytmpz), el._filtrCrop.getRGB(xo, yo), el.tolerancja )){
							_IZPix ++;
						} else if (el.kolorFixUzyj) {
							if (PW ( (_zrzut.getRGB (xtmpz, ytmpz)), el._kolorFix.ceilingKey( el._filtrCrop.getRGB(xo, yo)), el.tolerancja ) ){
								_IZPix ++;							
							};
						}

					}

				}
				
			}
		}
		//System.out.println ("_IZPix " + (_IZPix - el._sumaKontrolanPix));

		//if (diag) System.out.println("_B_SzukaczBUFF_A_OBRAZEK.java -Znalazłem elemntów " + test +" na " + el._sumaKontrolanPix);
		if (!el.kolorFixUzyj && _IZPix == el._sumaKontrolanPix) { // standardowe szukanie-precyzyjne
			return true;
		}else if (el.kolorFixUzyj && _IZPix >= el._sumaKontrolanPix){ // okresla kolor fikx i procentowe
			System.out.println ("Okreslenie procentowe " );
			return true;
		}else {
			return false;
		}
	}
	
	private boolean _okresltolerancjeProcentowa (int znalezone, _A_OBRAZEK el){
		int _tolerProc = 0;
		if (el.tolerProcentUzyj < 0) {
			_tolerProc = 0;
			System.err.println("tolerProc > niska wartość <0 >>0-80<<");
		}
			
		if (el.tolerProcentUzyj > 81){
			_tolerProc = 80;
			System.err.println("tolerProc > wysoka wartość >51 >>0-80<<");
		}
		
		int tolerancja = (el.tolerProcentUzyj * znalezone) /100;
		if (Math.abs(el.tolerProcentUzyj - tolerancja) > 0) return true;
		return false;
	}
	
	
	
	private boolean PW (int z, int o, int _tolerKoloru){
		if (_tolerKoloru < 0){
			System.err.println("tolerKoloru > za niska wartość < 0 >>0-200<<");
			_tolerKoloru = 0;
		}
		if (_tolerKoloru > 200){
			System.err.println("tolerKoloru > za wysoka wartość > 200 >>0-200<<");
			_tolerKoloru = 200;
		}
				
	 	int red1 = (z >> 16) & 0xff;
	 	int green1 = (z >> 8) & 0xff;
	 	int blue1 = (z) & 0xff;
	 	
    	//int alpha2 = (Z >> 24) & 0xff;
	  	int red2 = (o >> 16) & 0xff;
	 	int green2 = (o >> 8) & 0xff;
	 	int blue2 = (o) & 0xff;
	 	
	 	if (((Math.abs(red1 - red2)) <= _tolerKoloru) && ((Math.abs(green1 - green2)) <= _tolerKoloru) && ((Math.abs(blue1 - blue2)) <= _tolerKoloru)){
	 		return true;
	 	} else return false;
	}
	


	public static Integer odcinek (int Xodniesienia, int Yodniesienia, int xz, int yz) {
		return (int) Math.hypot( Math.abs (Xodniesienia - xz),(Math.abs (Yodniesienia - yz)) );
	}
	
	
	
}
